package team.kirohuji.shiro.credentials;

import java.util.concurrent.atomic.AtomicInteger;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;

import team.kirohuji.domain.user.User;
import team.kirohuji.service.user.UserService;
import team.kirohuji.utils.ShiroUtils;

/**
 * 这个类主要是进行认证
 * @author kirohuji
 *
 */
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    /**
     * @see Cache
     * passwordRetryCache
     */
    private Cache<String, AtomicInteger> passwordRetryCache;
    
    /**
     * @see SystemUserService
     * systemUserService
     */
    @Autowired
    private UserService userService;

    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
    	
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    /* 
     * 凭证的匹配
     * (non-Javadoc)
     * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher#doCredentialsMatch(org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo)
     * @param token 凭证
     * @param info 信息
     * @return boolean
     */
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = (String)token.getPrincipal();
        System.out.println("密码匹配");
        //retry count + 1
        AtomicInteger retryCount = passwordRetryCache.get(username);
        System.out.println("输入的密码次数:"+retryCount);
        if(retryCount == null) {
        	
            retryCount = new AtomicInteger(0);
            
            passwordRetryCache.put(username, retryCount);
        }
        if(retryCount.incrementAndGet() > 3) {
            //if retry count > 5 throw
            throw new ExcessiveAttemptsException("账户已锁定，请一小时后再试");
        }
        
        User user = userService.queryByLoginName(username);
        
        String password = ShiroUtils.MD5(new String((char[])token.getCredentials()), user.getSalt());
        
        if(!password.equals(user.getPassword())){
        	
        	throw new IncorrectCredentialsException("账号或密码不正确");
        }
        
        
        boolean matches = super.doCredentialsMatch(token, info);
        
        if(matches) {
            //clear retry count
            passwordRetryCache.remove(username);
        }
        return matches;
    }
}
